package com.sky.wsp.license.pkix;

import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
import org.bouncycastle.util.encoders.Base64;

import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.KeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Date;

/**
 * https://blog.csdn.net/qq_34823185/article/details/134303239
 */
public class PKCS12KeyStoreExample2 {
    private static final String P1_KEYSTORE = "p1_keystore.p12";
    private static final String PWD = "pwd123";
    private static final String ORG_1 = "org1";
    private static final String ORG_2 = "org2";

    public static void main(String[] args) {
        genP12();
//        testCert();

    }

    public static void testCert() {
        String base64Public = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiDtyBZmFd8AxQVJN9jMI9H5CaFwKjq4m14dxc+njKvg6D8AWWpkCdhajcGZ1JrDua/GXKZPuLHR/1Rt6QyIUjMNlKZhUZrNoxKOVLa4Awa7VmR+LDCWHUvuE9G1o6ZWjlS7fvw2QBYZ1nz9t6x4d+tlcMrZ5GV1we41uE1ZUDGDe0a5UIlgf3RG2quLPtuVhfKk1fMdfPYWe5M12Tt0zkPOEt63909/wqq6fiHVoKeDrfL35dCNDwT6sFCrnRNDpYwh7XhumtWuD7Q2akFAj8jCAJ1DHg0KiGkRRILN47pRdP7oZfDd//P4Qt9D+L2fQkbWf+qQUAYSWFyKWby9EqQIDAQAB";
        String base64Cert = "MIICqzCCAZOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAZMRcwFQYDVQQDDA5NeSBDZXJ0aWZpY2F0ZTAeFw0yNDA2MjEwMTAzNTFaFw0yNTA2MjEwMTAzNTFaMBkxFzAVBgNVBAMMDk15IENlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiDtyBZmFd8AxQVJN9jMI9H5CaFwKjq4m14dxc+njKvg6D8AWWpkCdhajcGZ1JrDua/GXKZPuLHR/1Rt6QyIUjMNlKZhUZrNoxKOVLa4Awa7VmR+LDCWHUvuE9G1o6ZWjlS7fvw2QBYZ1nz9t6x4d+tlcMrZ5GV1we41uE1ZUDGDe0a5UIlgf3RG2quLPtuVhfKk1fMdfPYWe5M12Tt0zkPOEt63909/wqq6fiHVoKeDrfL35dCNDwT6sFCrnRNDpYwh7XhumtWuD7Q2akFAj8jCAJ1DHg0KiGkRRILN47pRdP7oZfDd//P4Qt9D+L2fQkbWf+qQUAYSWFyKWby9EqQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAa0ofTsY4Xia+r/h1fHpnRKoKCPqVLaRFjxtCpwM+y/cZ1elz7oasXHmKPP0Mfy7TaNQRpg770AmB8YFWBqq5nXOkopo01D3gs8uQ9AYx16T7jrw7wr2ccPgIWgkBc2msYvfLTU0bV1S+QKkqFoH43QLkxqRsREhOa98VsZRwfq/M5l/zCawCFZ8UezYBNrZ5QDP0uNB9GPyvmXF9rjZ4vlcJc7J+rHgNxLWF8AdbXdIp6x1WmhCQhEXTeqdYv36ZmtbRN1kL/C3PRcLvFyoYa667hVFiRSG8ZXfNmRfC52OFdC0dmsf84l7A4l2bNN+x/hpc8MkeYjhEAPmGGUwnI";
        try {
            byte[] decodePublic = Base64.decode(base64Public);
            KeySpec publicKeySpec = new X509EncodedKeySpec(decodePublic);
            KeyFactory instance = KeyFactory.getInstance("RSA");
            PublicKey publicKey = instance.generatePublic(publicKeySpec);

            // 生成 X.509 证书
            byte[] decodeCert = Base64.decode(base64Cert);
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(decodeCert));
            PublicKey certPublicKey = certificate.getPublicKey();
            boolean equals = publicKey.equals(certPublicKey);
            System.out.printf(equals ? "equals" : "not equals\n");

            certificate.checkValidity();
            System.out.println("certificate in validity!");

            certificate.verify(publicKey);
            System.out.println("certificate verify success!");

            String issuer = certificate.getIssuerDN().getName();
            Date notBefore = certificate.getNotBefore();
            Date notAfter = certificate.getNotAfter();
            BigInteger serialNumber = certificate.getSerialNumber();

            System.out.printf("cert: %s, %d, %tc, %tc%n", issuer, serialNumber, notBefore, notAfter);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void genP12() {
        try {
            // 生成密钥对
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(2048);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();

            byte[] encodedPrivate = keyPair.getPrivate().getEncoded();
            byte[] encodedPublic = keyPair.getPublic().getEncoded();

            String base64Private = Base64.toBase64String(encodedPrivate);
            System.out.println(base64Private);
            String base64Public = Base64.toBase64String(encodedPublic);
            System.out.println(base64Public);

            byte[] decodePublic = Base64.decode(base64Public);
            KeyFactory instance = KeyFactory.getInstance("RSA");
            KeySpec publicKeySpec = new X509EncodedKeySpec(decodePublic);
            PublicKey publicKey = instance.generatePublic(publicKeySpec);

            // 生成 X.509 证书
            Certificate cert = generateCertificate(keyPair);
            byte[] encodedCert = cert.getEncoded();
            String base64Cert = Base64.toBase64String(encodedCert);
            System.out.println(base64Cert);
            byte[] decodeCert = Base64.decode(base64Cert);

            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(decodeCert));
            certificate.checkValidity();
            certificate.verify(publicKey);

            System.out.println("PKCS12 密钥库已生成！");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static Certificate generateCertificate(KeyPair keyPair) throws Exception {
        // 使用的签名算法RSA
        final AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256withRSA");
        // 使用的摘要算法SHA256
        final AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);

        X500Name issuer = new X500Name("CN=My Certificate");
        BigInteger serial = BigInteger.TEN;
        Date notBefore = new Date();
        Date notAfter = new Date(System.currentTimeMillis() + 100 * 24 * 60 * 60 * 1000);
        X500Name subject = new X500Name("CN=My Certificate");

        AsymmetricKeyParameter publicKeyParameter = PublicKeyFactory.createKey(keyPair.getPublic().getEncoded());
        SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(publicKeyParameter);

        //此种方式不行。生成证书不完整
        //SubjectPublicKeyInfo publicKeyInfo = new SubjectPublicKeyInfo(algId, publicKey.getEncoded());
        X509v3CertificateBuilder x509v3CertificateBuilder = new X509v3CertificateBuilder(
                issuer,
                serial,
                notBefore,
                notAfter,
                subject,
                publicKeyInfo);
//
//// 添加扩展信息 Extension
//// 基本约束
//        x509v3CertificateBuilder.addExtension(ExtensionUtils.getBasicConstraintsExtension(true));
//// CRL分布点
//        x509v3CertificateBuilder.addExtension(ExtensionUtils.getCRLDIstPointExtension(URINames));
//// 证书策略
//        x509v3CertificateBuilder.addExtension(ExtensionUtils.getCertificatePoliciesExtension());
//// 证书策略映射
//        x509v3CertificateBuilder.addExtension(ExtensionUtils.getPolicyMappingsExtension());
//// 秘钥用法
//        x509v3CertificateBuilder.addExtension(ExtensionUtils.getKeyUsageExtension());
//// 增强秘钥用法
//        x509v3CertificateBuilder.addExtension(ExtensionUtils.getExtendedKeyUsageExtension());
//// 备选使用者名称
//        x509v3CertificateBuilder.addExtension(ExtensionUtils.getSubjectAlternativeNameExtension());
//// 权限信息访问
//        x509v3CertificateBuilder.addExtension(ExtensionUtils.getAuthorityInfoAccessExtension('123'));
//// 颁发者密钥标识
//        x509v3CertificateBuilder.addExtension(ExtensionUtils.getAuthorityKeyIdentifierExtension(keyPair2.getPublic()));
//// 使用者密钥标识
//        x509v3CertificateBuilder.addExtension(ExtensionUtils.getSubjectKeyIdentifierExtension(keyPair.getPublic()));
//// 使用名称约束
//        x509v3CertificateBuilder.addExtension(ExtensionUtils.getNameConstraintsExtension());

        BcRSAContentSignerBuilder contentSignerBuilder = new BcRSAContentSignerBuilder(sigAlgId, digAlgId);
        AsymmetricKeyParameter privateKeyParameter = PrivateKeyFactory.createKey(keyPair.getPrivate().getEncoded());
        ContentSigner contentSigner = contentSignerBuilder.build(privateKeyParameter);

        X509CertificateHolder certificateHolder = x509v3CertificateBuilder.build(contentSigner);
        Certificate certificate = certificateHolder.toASN1Structure();

        return certificate;
    }

}
